package com.clp.protocol.iec104.client.pipeline.state;

import com.clp.protocol.iec104.apdu.ApduFactory;
import com.clp.protocol.iec104.apdu.UApdu;
import com.clp.protocol.iec104.client.InMaster;
import com.clp.protocol.iec104.client.async.MasterFuture;
import com.clp.protocol.iec104.client.async.MasterPromise;
import com.clp.protocol.iec104.client.async.sendapdu.SendStartDtVRes;
import com.clp.protocol.iec104.client.async.sendapdu.SendStopDtVRes;
import com.clp.protocol.iec104.client.pipeline.MPipelineManager;
import com.clp.protocol.iec104.common.res.SendTestFrVRes;
import com.clp.protocol.core.pdu.nbytepdu.FailedToSendFrameException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelPromise;

public class MInternalUApduSender {
    private final MPipelineManager pipelineManager;

    public MInternalUApduSender(MPipelineManager pipelineManager) {
        this.pipelineManager = pipelineManager;
    }

    public InMaster master() {
        return pipelineManager.getInMaster();
    }

    public ChannelFuture chSend(UApdu uApdu) {
        return master().channel().writeAndFlush(uApdu);
    }

    private ChannelPromise newChannelPromise() {
        return master().channel().newPromise();
    }

    /**
     * 发送启动传输激活
     */
    public MasterFuture<SendStartDtVRes> sendStartDtV() {
        InMaster master = master();
        MasterPromise<SendStartDtVRes> sendPromise = master().newPromise(new SendStartDtVRes());
        UApdu uApdu = ApduFactory.getUApduOfStartDtV();
        if (master.controlInfo().isStartedDt()) {
            sendPromise.getRes().setSendSuccess(false).setRecvAck(false);
            sendPromise.setFailure(new FailedToSendFrameException(uApdu));
            return sendPromise;
        }
        // 将 这个Promise注册到对应的状态中
        pipelineManager.getMDtInitControlStateHandler().register(sendPromise);
        chSend(uApdu);

        return sendPromise;
    }

    public MasterFuture<SendStopDtVRes> chSendStopDtV() {
        InMaster master = master();
        MasterPromise<SendStopDtVRes> sendPromise = master().newPromise(new SendStopDtVRes());
        UApdu uApdu = ApduFactory.getUApduOfStartDtV();
        if (!master.controlInfo().isStartedDt()) {
            sendPromise.getRes().setSendSuccess(false).setRecvAck(false);
            sendPromise.setFailure(new FailedToSendFrameException(uApdu));
            return sendPromise;
        }
        // 将 这个Promise注册到对应的状态中
        pipelineManager.getMDtInitControlStateHandler().register(sendPromise);
        chSend(uApdu);

        return sendPromise;
    }

    public MasterFuture<SendTestFrVRes> sendTestFrV() {
        InMaster master = master();
        MasterPromise<SendTestFrVRes> sendPromise = master().newPromise(new SendTestFrVRes());
        UApdu uApdu = ApduFactory.getUApduOfTestFrV();
        if (master.controlInfo().isTestingFr()) {
            sendPromise.getRes().setSendSuccess(false).setRecvAckSuccess(false);
            sendPromise.setFailure(new FailedToSendFrameException(uApdu));
            return sendPromise;
        }

        // 注册
        pipelineManager.getMt0T1T2T3ControlStateHandler().register(sendPromise);
        // 发送
        chSend(uApdu).addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                sendPromise.getRes().setSendSuccess(true);
                return;
            }
            sendPromise.getRes().setSendSuccess(false).setRecvAckSuccess(false);
            sendPromise.setFailure(new FailedToSendFrameException(uApdu));
        });
        return sendPromise;
    }

    public ChannelFuture chSendTestFrC() {
        return chSend(ApduFactory.getUApduOfTestFrC());
    }
}
